#include <stdlib.h>
#include <string.h>

#include <directfb.h>

#include "dtk_stack_layout.h"
#include "dtk_debug.h"

const DString DTK_LAYOUT_TYPE_STACK = "DTKLayoutStack";

static void stack_add (DTKLayout* self, DTKLayout* layout)
{
    dtk_list_prepend (&self->list, &layout->link);
    layout->parent = self;
    return;
}

static void stack_remove (DTKLayout* self, DTKLayout* layout)
{
    dtk_list_remove (&self->list, &layout->link);
    layout->parent = NULL;
    return;
}

static void stack_measure (DTKLayout* layout, DSize* size)
{
    DTKLayoutStack* stack = (DTKLayoutStack*)layout;
    DInt count;    
    DInt i;
    DList* list;
    DLink* link;
    DTKLayout* sub_layout;
    DSize preSize = {0, 0}, subSize;
    
    DTK_LAYOUT_TYPE_ASSERT(layout, DTK_LAYOUT_TYPE_STACK);

    list = dtk_layout_get_list (layout);
    count = dtk_list_get_count (list);
    if (count <= 0)
    {
        return;
    }

    dtk_layout_get_preSize (layout, size, &preSize);
    
    sub_layout = (DTKLayout*) dtk_list_get_first(list);    
    switch(stack->orientation)
    {
        case DTK_VERTICAL:
        {
            DInt height = 0;
            subSize.w = preSize.w;
            for (i = 0; i < count; i++)
            {
                subSize.h = (preSize.h - height)/ (count - i);
                if (dtk_actor_is_visiable (sub_layout->actor))
                {
                    if (sub_layout->measure)
                    {
                        sub_layout->measure (sub_layout, &subSize);
                    }
                    if (sub_layout->desiredSize.w > subSize.w)
                    {
                        preSize.w = subSize.w = sub_layout->desiredSize.w;
                    }
                    height += sub_layout->desiredSize.h;
                }
                link = dtk_list_get_next(dtk_layout_get_link(sub_layout));
                sub_layout = (DTKLayout*)DLINKDATA(link);
            }
            if (height != 0)
            {
                preSize.h = height;
            }
            break;
        }
        case DTK_HORIZONTAL:
        {
            DInt width = 0;
            subSize.h = preSize.h;
            for (i = 0; i < count; i++)
            {
                if (dtk_actor_is_visiable (sub_layout->actor))
                {
                    subSize.w = (preSize.w - width)/ (count - i);
                    if (sub_layout->measure)
                    {
                        sub_layout->measure (sub_layout, &subSize);
                    }
                    
                    if (sub_layout->desiredSize.h > subSize.h)
                    {
                        preSize.h = subSize.h = sub_layout->desiredSize.h;
                    }
                    
                    width += sub_layout->desiredSize.w;                   
                }
                link = dtk_list_get_next(dtk_layout_get_link(sub_layout));
                sub_layout = (DTKLayout*)DLINKDATA(link);
            }
            if (width != 0)
            {
                preSize.w = width;
            }
            break;
        }
    }

    dtk_layout_set_desiredSize (layout, &preSize);
    
    return;
}

static void stack_arrange (DTKLayout* layout, DRectangle* rect)
{
    DTKLayoutStack* stack = (DTKLayoutStack*)layout;
    DSize preSize, subSize;
    DInt i, count;
    DTKLayout* sub_layout;
    DList* list;
    DLink* link;
    

    DTK_LAYOUT_TYPE_ASSERT(layout, DTK_LAYOUT_TYPE_STACK);

    if (layout->position.x ==  rect->x
        && layout->position.y ==  rect->y
        && layout->actual.w == rect->width
        && layout->actual.h == rect->height)
    {
        return;
    }

    dtk_layout_set_redraw (layout, NULL, DTK_TRUE);

    layout->position.x = rect->x;
    layout->position.y = rect->y;
    layout->actual.w = rect->width;
    layout->actual.h = rect->height;
    printf ("%s:(%d, %d, %d, %d)\n", __func__,
        layout->position.x,
        layout->position.y,
        layout->actual.w,
        layout->actual.h);

    list = dtk_layout_get_list (layout);

    count = dtk_list_get_count (list);
    if (count <= 0)
    {
        return;
    }

    sub_layout = (DTKLayout*)dtk_list_get_first (list);
    switch (stack->orientation)
    {
        case DTK_VERTICAL:
        {
            DInt y = rect->y;
            for (i = 0; i < count; i++)
            {
                if (dtk_actor_is_visiable (sub_layout->actor))
                {
                    DRectangle sub_rect;
                    sub_rect.x = 0;
                    sub_rect.y = y;
                    sub_rect.width = sub_layout->desiredSize.w;
                    sub_rect.height = sub_layout->desiredSize.h;
                    if (sub_layout->arrange)
                    {
                        sub_layout->arrange (sub_layout, &sub_rect);
                    }
                    y += sub_layout->desiredSize.h;
                }
                link = dtk_list_get_next(dtk_layout_get_link(sub_layout));
                sub_layout = (DTKLayout*)DLINKDATA(link);
                
            }
            break;
        }
        case DTK_HORIZONTAL:
        {
            DInt x = rect->x;
            for (i = 0; i < count; i++)
            {
                if (dtk_actor_is_visiable (sub_layout->actor))
                {
                    DRectangle sub_rect;
                    sub_rect.x = x;
                    sub_rect.y = 0;
                    sub_rect.width = sub_layout->desiredSize.w;
                    sub_rect.height = sub_layout->desiredSize.h;
                    printf ("%s:(%d, %d, %d, %d)\n", sub_layout->actor->type, 
                        sub_rect.x, sub_rect.y, sub_rect.width, sub_rect.height);
                    if (sub_layout->arrange)
                    {
                        sub_layout->arrange (sub_layout, &sub_rect);
                    }
                    x += sub_layout->desiredSize.w;
                }
                link = dtk_list_get_next(dtk_layout_get_link(sub_layout));
                sub_layout = (DTKLayout*)DLINKDATA(link);
            }
            break;
        }
    }    
    
    return;
}

static void stack_release (DTKLayout* layout)
{
    if (layout == NULL)
    {
        return;
    }

    dtk_layout_remove_sub_all(layout);
    return;
}

void stack_update (DTKLayout* layout)
{
    DTKActor* actor;
    DInt i = 0;
    DTKLayout* sub_layout;
    DTKContainer* content;
    DInt actor_count;
    DInt layout_count;
    
    if (layout == NULL)
    {
        return;
    }
    
    return;
}

DTKLayout* dtk_stack_layout_new(DTKActor* actor, DTKOrientation orientation)
{
    DTKLayout* layout;
    DTKLayoutStack* stack;

    layout = dtk_layout_new (sizeof(DTKLayoutStack),
        DTK_LAYOUT_TYPE_STACK, actor);
    stack = (DTKLayoutStack*) layout;

    stack->orientation = orientation;
    layout->add = stack_add;
    layout->remove = stack_remove;
    layout->update = stack_update;
    layout->measure = stack_measure;
    layout->arrange = stack_arrange;
    layout->release = stack_release;

    return layout;    
}

void dtk_stack_layout_set_orientation (DTKLayout* self, DTKOrientation orientation)
{
    DTKLayoutStack* stack = (DTKLayoutStack*)self;
    DTK_ASSERT(self != NULL);

    if (stack->orientation != orientation)
    {
        stack->orientation = orientation;
        dtk_actor_update(self->actor, NULL, DTK_TRUE);
    }
    
    return;
}
